[IA64] Implement fast hypercall for physdevop eoi.
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Mon, 2 Oct 2006 20:09:49 +0000 (14:09 -0600)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Mon, 2 Oct 2006 20:09:49 +0000 (14:09 -0600)
Eoi is a very frequent hypercall which has only one argument passed through
a structure.  To avoid the xencomm overhead, a new hypercall is created
and the argument is passed by value.

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
xen/arch/ia64/xen/hypercall.c
xen/include/asm-ia64/dom_fw.h
xen/include/public/arch-ia64.h

index 169a2c03cff7af5792b2dde6f0257bc810fe281f..8a21141179f94bdf56c0e12403fceb2d3cac847f 100644 (file)
@@ -259,6 +259,18 @@ xencomm_arch_hypercall_hvm_op(int cmd, void *arg)
        return _hypercall2(unsigned long, hvm_op, cmd, arg);
 }
 
+static inline int
+HYPERVISOR_physdev_op(int cmd, void *arg)
+{
+       switch (cmd) {
+       case PHYSDEVOP_eoi:
+               return _hypercall1(int, ia64_fast_eoi,
+                                  ((struct physdev_eoi *)arg)->irq);
+       default:
+               return xencomm_hypercall_physdev_op(cmd, arg);
+       }
+}
+
 extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
 static inline void exit_idle(void) {}
 #define do_IRQ(irq, regs) ({                   \
@@ -377,7 +389,6 @@ HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
 #define HYPERVISOR_multicall xencomm_mini_hypercall_multicall
 #define HYPERVISOR_xen_version xencomm_mini_hypercall_xen_version
 #define HYPERVISOR_console_io xencomm_mini_hypercall_console_io
-#define HYPERVISOR_physdev_op xencomm_mini_hypercall_physdev_op
 #define HYPERVISOR_hvm_op xencomm_mini_hypercall_hvm_op
 #ifdef CONFIG_VMX_GUEST
 #define HYPERVISOR_memory_op 0
@@ -391,7 +402,6 @@ HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
 #define HYPERVISOR_multicall xencomm_hypercall_multicall
 #define HYPERVISOR_xen_version xencomm_hypercall_xen_version
 #define HYPERVISOR_console_io xencomm_hypercall_console_io
-#define HYPERVISOR_physdev_op xencomm_hypercall_physdev_op
 #define HYPERVISOR_hvm_op xencomm_hypercall_hvm_op
 #define HYPERVISOR_memory_op xencomm_hypercall_memory_op
 #endif
index c9728f530bdd47443d457323a3431a5a6b05a0ab..8fc4c4c3cbc844cd0a4eb33cdb86511ac04889de 100644 (file)
@@ -123,6 +123,20 @@ xen_hypercall (struct pt_regs *regs)
        return IA64_NO_FAULT;
 }
 
+static IA64FAULT
+xen_fast_hypercall (struct pt_regs *regs)
+{
+       uint32_t cmd = (uint32_t)regs->r2;
+       switch (cmd) {
+       case __HYPERVISOR_ia64_fast_eoi:
+               regs->r8 = pirq_guest_eoi(current->domain, regs->r14);
+               break;
+       default:
+               regs->r8 = -ENOSYS;
+       }
+       return IA64_NO_FAULT;
+}
+
 static void
 fw_hypercall_ipi (struct pt_regs *regs)
 {
@@ -187,8 +201,8 @@ fw_hypercall_fpswa (struct vcpu *v)
        return PSCBX(v, fpswa_ret);
 }
 
-static IA64FAULT
-fw_hypercall (struct pt_regs *regs)
+IA64FAULT
+ia64_hypercall(struct pt_regs *regs)
 {
        struct vcpu *v = current;
        struct sal_ret_values x;
@@ -199,7 +213,13 @@ fw_hypercall (struct pt_regs *regs)
 
        perfc_incra(fw_hypercall, index >> 8);
        switch (index) {
-           case FW_HYPERCALL_PAL_CALL:
+       case FW_HYPERCALL_XEN:
+               return xen_hypercall(regs);
+
+       case FW_HYPERCALL_XEN_FAST:
+               return xen_fast_hypercall(regs);
+
+       case FW_HYPERCALL_PAL_CALL:
                //printf("*** PAL hypercall: index=%d\n",regs->r28);
                //FIXME: This should call a C routine
 #if 0
@@ -250,7 +270,7 @@ fw_hypercall (struct pt_regs *regs)
                        regs->r10 = y.v1; regs->r11 = y.v2;
                }
                break;
-           case FW_HYPERCALL_SAL_CALL:
+       case FW_HYPERCALL_SAL_CALL:
                x = sal_emulator(vcpu_get_gr(v,32),vcpu_get_gr(v,33),
                        vcpu_get_gr(v,34),vcpu_get_gr(v,35),
                        vcpu_get_gr(v,36),vcpu_get_gr(v,37),
@@ -258,46 +278,35 @@ fw_hypercall (struct pt_regs *regs)
                regs->r8 = x.r8; regs->r9 = x.r9;
                regs->r10 = x.r10; regs->r11 = x.r11;
                break;
-           case FW_HYPERCALL_SAL_RETURN:
+       case FW_HYPERCALL_SAL_RETURN:
                if ( !test_and_set_bit(_VCPUF_down, &v->vcpu_flags) )
                        vcpu_sleep_nosync(v);
                break;
-           case FW_HYPERCALL_EFI_CALL:
+       case FW_HYPERCALL_EFI_CALL:
                efi_ret_value = efi_emulator (regs, &fault);
                if (fault != IA64_NO_FAULT) return fault;
                regs->r8 = efi_ret_value;
                break;
-           case FW_HYPERCALL_IPI:
+       case FW_HYPERCALL_IPI:
                fw_hypercall_ipi (regs);
                break;
-           case FW_HYPERCALL_SET_SHARED_INFO_VA:
+       case FW_HYPERCALL_SET_SHARED_INFO_VA:
                regs->r8 = domain_set_shared_info_va (regs->r28);
                break;
-           case FW_HYPERCALL_FPSWA:
+       case FW_HYPERCALL_FPSWA:
                fpswa_ret = fw_hypercall_fpswa (v);
                regs->r8  = fpswa_ret.status;
                regs->r9  = fpswa_ret.err0;
                regs->r10 = fpswa_ret.err1;
                regs->r11 = fpswa_ret.err2;
                break;
-           default:
+       default:
                printf("unknown ia64 fw hypercall %lx\n", regs->r2);
                regs->r8 = do_ni_hypercall();
        }
        return IA64_NO_FAULT;
 }
 
-IA64FAULT
-ia64_hypercall (struct pt_regs *regs)
-{
-       unsigned long index = regs->r2;
-
-       if (index >= FW_HYPERCALL_FIRST_ARCH)
-           return fw_hypercall (regs);
-       else
-           return xen_hypercall (regs);
-}
-
 unsigned long hypercall_create_continuation(
        unsigned int op, const char *format, ...)
 {
index 841ea9e200f605d64beadac6d5a278040c96fae0..baae6d08fcc64b6d5262fc8933523b4872609ccb 100644 (file)
 #define FW_HYPERCALL_NUM_MASK_HIGH     ~0xffUL
 #define FW_HYPERCALL_NUM_MASK_LOW       0xffUL
 
+/* Xen hypercalls are 0-63.  */
+#define FW_HYPERCALL_XEN               0x0000UL
+
+/* Define some faster and lighter hypercalls.
+   See definitions in arch-ia64.h */
+#define FW_HYPERCALL_XEN_FAST          0x0200UL
+
 /*
  * PAL can be called in physical or virtual mode simply by
  * branching to pal_entry_point, which is found in one of the
index 08e219784679bf7e747d9ca6a7b0d4bb4d1310fa..aa51d3297d5cbb61ce4280c1da1d3354d990622e 100644 (file)
@@ -428,6 +428,9 @@ struct xen_ia64_boot_param {
 #define HYPERPRIVOP_GET_PSR            0x19
 #define HYPERPRIVOP_MAX                        0x19
 
+/* Fast and light hypercalls.  */
+#define __HYPERVISOR_ia64_fast_eoi     0x0200
+
 /* Xencomm macros.  */
 #define XENCOMM_INLINE_MASK 0xf800000000000000UL
 #define XENCOMM_INLINE_FLAG 0x8000000000000000UL